<?php

namespace app;
use APP\MathExpression;
use app\core\App;
use app\core\Log;

class Route
{

    /**
     * 函数列表
     * @var array
     */
    private static $funList = [];

    /**
     * 变量列表
     * @var array
     */
    private static $varList = [];


    /**
     * 定义函数
     * @param mixed $rule
     * @param mixed $fun
     * @param mixed $type
     * @return void
     */
    public static function fun($rule, $fun, $type = 'Fun')
    {

        $info = debug_backtrace()[$type == 'Fun' ? 0 : 1];
        $ruleList = explode('/', $rule);
        $funName = $type . '_' . md5($ruleList[0]);
        if (array_key_exists($funName, self::$funList)) {
            $error = [
                'type' => 'Warning',
                'line' => self::$funList[$funName]['fileinfo']['line'],
                'path' => self::$funList[$funName]['fileinfo']['path'],
                'message' => '函数重复定义：' . $ruleList[0]

            ];
            Log::log($error);
            return;
        }
        array_shift($ruleList);
        self::$funList[$funName]['args'] = $ruleList;
        self::$funList[$funName]['closure'] = $fun;
        self::$funList[$funName]['fileinfo']['path'] = $info['file'];
        self::$funList[$funName]['fileinfo']['line'] = $info['line'];
        //print_r(self::$funList);

    }


    /**
     * 调用函数
     * @param mixed $funName
     * @param mixed $args
     * @param mixed $rowName
     * @return mixed
     */
    public static function callFun($funName, $args,$rowName)
    {
        if (isset(self::$funList[$funName])) {
            $closure = self::$funList[$funName]['closure'];
            $params = self::handle($closure, $args, self::$funList[$funName]['args']);
            //print_r($closure);
            $messageHandleClass = App::_getMessageHandlerClass()->method;

            $messageHandleClass->message = app::_message()->get();
            $messageHandleClass->frameConfig = App::_getFrameConfig();
            $closure = $closure->bindTo($messageHandleClass);
            return call_user_func_array($closure, $params);
        } else {
            $info = debug_backtrace();
            $fileInfo =$info[2]['object']->fileInfo;
            //print_r($info);
            $error = [
                'type' => 'Warning',
                'line' => $fileInfo['line'],
                'path' => $fileInfo['path'],
                'message' => '调用没有定义的函数：' . $info[0]['args'][2]

            ];
            Log::log($error);
            return false;
        }

    }




    /**
     * 定义变量
     * @param mixed $rule
     * @param mixed $var
     * @return void
     */

    public static function var($rule, $var)
    {
        if (is_callable($var)) {
            return self::fun($rule, $var, 'Var');
        }
        //print_r(self::$funList);
    }


    /**
     * 读取变量
     * @param mixed $varName
     * @return mixed
     */
    public static function getVar($varName)
    {
        if (isset(self::$funList[$varName])) {
            return self::callFun($varName, [],'varCall');
        }
        $messageHandleClass = App::_getMessageHandlerClass()->method;
        if (isset($messageHandleClass->$varName)) {
            return $messageHandleClass->$varName;
        }
    }


    /**
     * 处理参数
     * @param mixed $closure
     * @param mixed $params
     * @param mixed $args
     * @return array
     */
    private static function handle($closure, $params, $args)
    {
        $arguments = [];
        if (is_object($closure)) {
            $reflection = new \ReflectionFunction($closure);
            $arguments = $reflection->getParameters();
        }


        $argList = [];
        foreach ($args as $key => $value) {
            $argList[mb_substr($value, 1)] = $params[$key];

        }

        $paramsList = [];
        foreach ($arguments as $key => $value) {
            if (array_key_exists($value->getName(), $argList)) {
                $paramsList[] = $argList[$value->getName()];
            }
        }
        return $paramsList;

    }

    public static function getClassName($className) {
        return App::_getMessageHandlerClass()->prefix . md5($className);
    }



}